package com.zhiwang.planet.widget;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuffXfermode;
import android.os.Build;
import androidx.annotation.Nullable;
import com.google.android.material.animation.ArgbEvaluatorCompat;
import androidx.viewpager.widget.ViewPager;
import androidx.appcompat.widget.AppCompatImageView;
import android.util.AttributeSet;
import android.view.View;
import android.widget.FrameLayout;

import com.zhiwang.planet.R;

import java.lang.ref.WeakReference;

import static androidx.core.content.ContextCompat.getColor;

public class CircleIndicator extends FrameLayout {
    private static final String TAG = "CircleIndicator";
    PorterDuffXfermode SRC_INXfermode;
    int defaultColor = Color.parseColor("#000000");
    int bubbleMode = 1;
    int gap;
    int number;
    int gravity;
    int color;
    int craterColor = Color.parseColor("#EFE5FC");
    int radius;
    float ratio;
    int currentPos = 0;
    Paint paint;
    ViewPager viewPager;
    AppCompatImageView indicatorView;

    private static final int LEFT = 0;
    private static final int CENTER = 1;
    private static final int RIGHT = 2;

    private static final int MODE_BACKGROUND = 0;
    private static final int MODE_OVERLAY = 1;

    private ArgbEvaluatorCompat argbEvaluator = ArgbEvaluatorCompat.getInstance();


    public CircleIndicator(Context context) {
        super(context);
    }

    public CircleIndicator(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.CircleIndicator);
        color = array.getColor(R.styleable.CircleIndicator_color, defaultColor);
        radius = array.getDimensionPixelSize(R.styleable.CircleIndicator_radius, 0);
        number = array.getInteger(R.styleable.CircleIndicator_number, 0);
        gap = array.getDimensionPixelSize(R.styleable.CircleIndicator_gap, 0);
        gravity = array.getInteger(R.styleable.CircleIndicator_bubble_gravity, CENTER);
        array.recycle();
        paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setColor(color);
        paint.setStyle(Paint.Style.FILL);
//        SRC_INXfermode = ic_generate_new PorterDuffXfermode(SRC_IN);
        paint.setAntiAlias(true);
    }

    public void setViewPager(ViewPager v) {
        WeakReference<ViewPager> wk = new WeakReference<>(v);
        viewPager = wk.get();
        viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
                currentPos = position;
                ratio = positionOffset;
                invalidate();

            }

            @Override
            public void onPageSelected(int position) {

            }

            @Override
            public void onPageScrollStateChanged(int state) {
            }
        });
    }

    public CircleIndicator(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int width = MeasureSpec.getSize(widthMeasureSpec);
        int height = MeasureSpec.getSize(heightMeasureSpec);

        if (MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.AT_MOST)
            width = 2 * radius * number + gap * (number - 1);

        height = Math.max(height, radius * 2);
        setMeasuredDimension(width, height);
    }


    @Override
    public void onViewAdded(View child) {
        super.onViewAdded(child);
        indicatorView = (AppCompatImageView) child;
    }

    @SuppressLint("RestrictedApi")
    @Override
    protected void dispatchDraw(Canvas canvas) {
        int evaluateColor;
        if (currentPos == 0)
            evaluateColor = argbEvaluator.evaluate(ratio, getColor(getContext(), R.color.indicator_color_start), getColor(getContext(), R.color.indicator_color_middle));
        else if (currentPos == 1)
            evaluateColor = argbEvaluator.evaluate(ratio, getColor(getContext(), R.color.indicator_color_middle), getColor(getContext(), R.color.indicator_color_end));
        else
            evaluateColor = getColor(getContext(), R.color.indicator_color_end);
        float centerX = 0;
        float offset;
        switch (gravity) {
            case LEFT:
                centerX = radius;
                break;
            case CENTER:
                centerX = getMeasuredWidth() / 2 - (2 * radius * number + gap * (number - 1)) / 2 + radius;
                break;
            case RIGHT:
                centerX = radius + (getMeasuredWidth() - (2 * radius * number + gap * (number - 1)));
                break;
        }
        offset = centerX;
        float centerY = getMeasuredHeight() / 2;
        paint.setXfermode(null);
        canvas.drawARGB(0, 0, 0, 0);
        int id = 0;
        if (bubbleMode == MODE_BACKGROUND)
            id = canvas.save();
        paint.setColor(craterColor);
        for (int i = 0; i < number; i++) {
            canvas.drawCircle(centerX, centerY, radius, paint);
            centerX += (2 * radius + gap);
        }
        paint.setColor(evaluateColor);
        centerX = offset + (ratio + currentPos) * (2 * radius + gap);
        if (bubbleMode == MODE_BACKGROUND)
            canvas.restoreToCount(id);

        int left = (int) (centerX - indicatorView.getMeasuredWidth() / 2);
        int top = (int) (centerY - indicatorView.getMeasuredHeight() / 2);


        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            indicatorView.setImageTintList(ColorStateList.valueOf(evaluateColor));
        } else {
            indicatorView.setSupportBackgroundTintList(ColorStateList.valueOf(evaluateColor));
        }
        indicatorView.layout(left, top, left + indicatorView.getMeasuredWidth(), top + indicatorView.getMeasuredHeight());
        super.dispatchDraw(canvas);
    }

}
